//
//  ChatViewController+Scrolling.swift
//  Chatty
//
//  Created by zuber on 2018/10/16.
//  Copyright © 2018年 zuber. All rights reserved.
//

import UIKit

enum CellVerticalEdge {
  case top
  case bottom
}

extension CGFloat {
  static let bma_epsilon: CGFloat = 0.001
}

extension ChatViewController{
  
  func isScrolledAtBottom() -> Bool {
    guard self.collectionView.numberOfSections > 0 && self.collectionView.numberOfItems(inSection: 0) > 0 else { return true }
    let sectionIndex = self.collectionView.numberOfSections - 1
    let itemIndex = self.collectionView.numberOfItems(inSection: sectionIndex) - 1
    let lastIndexPath = IndexPath(item: itemIndex, section: sectionIndex)
    return self.isIndexPathVisible(lastIndexPath, atEdge: .bottom)
  }
  
  func isIndexPathVisible(_ indexPath: IndexPath, atEdge edge: CellVerticalEdge) -> Bool {
    if let attributes = self.collectionView.collectionViewLayout.layoutAttributesForItem(at: indexPath) {
      let visibleRect = self.visibleRect()
      // indexpath frame是否和collectionview的可见区域相交
      let intersection = visibleRect.intersection(attributes.frame)
      if edge == .top {
        return abs(intersection.minY - attributes.frame.minY) < CGFloat.bma_epsilon
      } else {
        return abs(intersection.maxY - attributes.frame.maxY) < CGFloat.bma_epsilon
      }
    }
    return false
  }
  
  func visibleRect() -> CGRect {
    let contentInset = self.collectionView.contentInset
    let collectionViewBounds = self.collectionView.bounds
    let contentSize = self.collectionView.collectionViewLayout.collectionViewContentSize
    return CGRect(x: 0, y: self.collectionView.contentOffset.y + contentInset.top, width: collectionViewBounds.width, height: min(contentSize.height, collectionViewBounds.height - contentInset.top - contentInset.bottom))
  }
  
  @objc
  func scrollToBottom(animated: Bool) {
    // 取消当前的滚动
    self.collectionView.setContentOffset(self.collectionView.contentOffset, animated: false)
    
    // Note that we don't rely on collectionView's contentSize. This is because it won't be valid after performBatchUpdates or reloadData
    // After reload data, collectionViewLayout.collectionViewContentSize won't be even valid, so you may want to refresh the layout manually
    let offsetY = max(-self.collectionView.contentInset.top, self.collectionView.collectionViewLayout.collectionViewContentSize.height - self.collectionView.bounds.height + self.collectionView.contentInset.bottom)
    
    // Don't use setContentOffset(:animated). If animated, contentOffset property will be updated along with the animation for each frame update
    // If a message is inserted while scrolling is happening (as in very fast typing), we want to take the "final" content offset (not the "real time" one) to check if we should scroll to bottom again
    if animated {
      UIView.animate(withDuration: self.constants.updatesAnimationDuration, animations: { () -> Void in
        self.collectionView.contentOffset = CGPoint(x: 0, y: offsetY)
      })
    } else {
      self.collectionView.contentOffset = CGPoint(x: 0, y: offsetY)
    }
  }
}





